--
-- CSSE2000 8 Bit Microprocessor
-- Copyright (C) 2011 Nathan Rossi (University of Queensland)
--
-- THIS DESIGN/CODE IS PROVIDED TO YOU UNDER THE FOLLOWING LICENSE:
--
-- All material is restricted to use in the CSSE2000 Project for 2011.
-- You may not redistribute the file/code/design, without the consent of the author.
--
-- DO NOT MODIFY THIS FILE
--

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

library work;
use work.proc_package.ALL;

entity proc_progcounter is
	port (
		clk : in std_logic;
		rst : in std_logic;
		en : in std_logic;
		
		mode : in PROC_PC_MODE;
		
		value_in : in PROC_PROG_ADDR_TYPE;
		value_out : out PROC_PROG_ADDR_TYPE
	);
end proc_progcounter;

architecture Behavioral of proc_progcounter is

	-- Default Increment Value
	constant increment_value : PROC_PROG_ADDR_TYPE := conv_std_logic_vector(1, PROC_PROG_ADDR_SIZE);

	-- Counter Stored Signal
	signal prog_counter : PROC_PROG_ADDR_TYPE := (others => '0');
begin

	value_out <= prog_counter;

	-- Counter changes Synchronously (Async Reset)
	process(clk, rst)
		variable new_counter_value : PROC_PROG_ADDR_TYPE := (others => '0');
	begin
		if rising_edge(clk) then
			if (rst = '1') then
				-- Reset the counter asynchronously
				prog_counter <= (others => '0');
			elsif en = '1' then
				-- Counter is enabled, perform requested action.
				new_counter_value := prog_counter;
				case mode is
					when PC_JUMP_RELATIVE => -- Relative Jump, PC <= PC + K + 1
						new_counter_value := new_counter_value + increment_value + value_in;
					when PC_JUMP_ABSOLUTE =>
						new_counter_value := value_in;
					when others => -- PC_NORMAL
						new_counter_value := new_counter_value + increment_value;
				end case;
				-- Set the signal to the temporary variable.
				prog_counter <= new_counter_value;
			end if;
		end if;
	end process;
	
end Behavioral;

